#include <vector>
#include <iostream>

#include "DTDDocument.h"
#include "XMLDocument.h"
#include "XMLElement.h"
#include "XMLEntity.h"
#include "DTDEntityElement.h"
#include "DTDEntityAttList.h"

using namespace std;

DTDDocument::DTDDocument()
{

}

void DTDDocument::addDtdElement(DTDEntityElement* entity)
{
	this->childList.push_back(entity);
	this->elementList.push_back(entity);
}

void DTDDocument::addDtdAttList(DTDEntityAttList* entity)
{
	this->childList.push_back(entity);
	this->attListList.push_back(entity);
}

bool DTDDocument::checkDocumentValidity(XMLElement* balise)
/*
 * Algo :
 *	1) Check attributes (optional)
 *	2) Check balises
 * 	3) Check child list (rec.)
 */
{
	bool error = false;
	vector<XMLNode*> childList = balise->getChildList();

	// 1) Check attributes

	// 2) Check balises
	vector<DTDEntityElement*>::iterator identifiedDtdElement;

	// On cherche une règle correspondant à la balise
	for( identifiedDtdElement = this->elementList.begin();identifiedDtdElement<this->elementList.end();identifiedDtdElement++)
	{
		if((*identifiedDtdElement)->getName() == balise->getNodeName())
		{
			break;
		}
	}

	if(identifiedDtdElement != elementList.end())
	{	//Si règle trouvée
		vector<string> balises;

		for(vector<XMLNode*>::iterator i=childList.begin();i<childList.end();i++)
		{	// On récupère le nom des noeuds de childList
			balises.push_back((*i)->getNodeName());
		}

		if((*identifiedDtdElement)->checkChildListValidity(balises))
		{	// Si une erreur pour cette balise
			cerr << "Error : incompatibility between DTD element '" << (*identifiedDtdElement)->toString() << "' and balise '" << balise->getNodeName() << "'" << endl;
			error = true;
		}

	}
	else
	{	//Si pas de règle trouvée
		cerr << "Error : No DTD Element founded for balise" << balise->getNodeName() << endl;
		error = true;
	}


	// 3) Check childList
	for(vector<XMLNode*>::iterator node=childList.begin();node<childList.end();node++)
	{	// On teste maintenant les enfants

		if((*node)->getNodeName() != "#PCDATA") // Si le noeud n'est pas un XMLText
		{	// on teste récrusivement  (car pas de test sur les PCDATA)
			error = error || this->checkDocumentValidity((XMLElement*)*node);
		}
	}

	return error;
}
